package com.excesys.exsecs.energy.service.impl;

import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNode;
import cn.hutool.core.lang.tree.TreeUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.excesys.exsecs.energy.entity.*;
import com.excesys.exsecs.energy.mapper.DimSubitemMapper;
import com.excesys.exsecs.energy.mapper.RegDevMapper;
import com.excesys.exsecs.energy.service.DevSubitemMapService;
import com.excesys.exsecs.energy.service.DimSubitemService;
import com.excesys.exsecs.energy.service.PowerHourFlowService;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.MapUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Year;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 能耗维度：分项无其他选项分项按国标列4项：照明，空调，动力，特殊，这4个基本项不能删除修改，但可以增删改查子项
 *
 * @author lxc
 * @date 2024-03-04 14:09:43
 */
@Service
@RequiredArgsConstructor
public class DimSubitemServiceImpl extends ServiceImpl<DimSubitemMapper, DimSubitem> implements DimSubitemService {

    private final DevSubitemMapService devSubitemMapService;
    private final RegDevMapper regDevMapper;

    private final PowerHourFlowService powerHourFlowService;

    @Override
    public List<Tree<Long>> queryTree(DimSubitem dimSubitem) {
        List<DimSubitem> subitemList = this.list(Wrappers.<DimSubitem>lambdaQuery()
                .like(StringUtils.isNotBlank(dimSubitem.getSubitemName()), DimSubitem::getSubitemName, dimSubitem.getSubitemName()));
        if (CollectionUtils.isNotEmpty(subitemList)) {
            List<Long> branchIds = subitemList.stream().map(DimSubitem::getId).collect(Collectors.toList());
            List<DevSubitemMap> devSubitemMaps = devSubitemMapService.list(Wrappers.<DevSubitemMap>lambdaQuery().in(DevSubitemMap::getSubitemId, branchIds));
            if (CollectionUtils.isNotEmpty(devSubitemMaps)) {
                Map<Long, List<DevSubitemMap>> maps = devSubitemMaps.stream().collect(Collectors.groupingBy(DevSubitemMap::getSubitemId));
                List<String> unitNos = devSubitemMaps.stream().map(DevSubitemMap::getUnitNo).distinct().collect(Collectors.toList());
                List<RegDev> regDevs = regDevMapper.selectList(Wrappers.<RegDev>lambdaQuery().in(RegDev::getUnitNo, unitNos));
                maps.forEach((key, value) -> {
                    value.forEach(it -> {
                        String unitNo = it.getUnitNo();
                        RegDev regDev = regDevs.stream().filter(f -> f.getUnitNo().equals(unitNo)).findFirst().orElse(null);
                        if (ObjectUtils.isNotEmpty(regDev)) {
                            it.setUnitName(regDev.getUnitName());
                            it.setDeviceNo(regDev.getDeviceNo());
                            it.setDeviceName(regDev.getDeviceName());
                            it.setEnergyType(regDev.getEnergyType());
                        }
                    });
                });

                for (DimSubitem subitem : subitemList) {
                    List<DevSubitemMap> devSubitemMaps2 = maps.get(subitem.getId());
                    if (CollectionUtils.isNotEmpty(devSubitemMaps2)) {
                        subitem.setDevSubitemMapList(devSubitemMaps2);
                        List<String> collect = devSubitemMaps2.stream().map(DevSubitemMap::getUnitName).collect(Collectors.toList());
                        subitem.setDevSubitemNameStr(String.join(",", collect));
                    }
                }
            }
        }
        List<TreeNode<Long>> collect = subitemList.stream().map(getNodeFunction()).collect(Collectors.toList());
        return TreeUtil.build(collect, 0L);
    }

    @Override
    public DimSubitem getSubitemById(Long id) {
        DimSubitem subitem = this.getById(id);
        if (ObjectUtils.isNotEmpty(subitem)) {
            List<DevSubitemMap> devSubitemMaps = devSubitemMapService.list(Wrappers.<DevSubitemMap>lambdaQuery().eq(DevSubitemMap::getSubitemId, subitem.getId()));
            if (CollectionUtils.isNotEmpty(devSubitemMaps)) {
                devSubitemMaps.forEach(dev -> {
                    List<RegDev> regDevs = regDevMapper.selectList(Wrappers.<RegDev>lambdaQuery().eq(RegDev::getUnitNo, dev.getUnitNo()));
                    if (CollectionUtils.isNotEmpty(regDevs)) {
                        RegDev regDev = regDevs.get(0);
                        dev.setUnitName(regDev.getUnitName());
                        dev.setDeviceNo(regDev.getDeviceNo());
                        dev.setDeviceName(regDev.getDeviceName());
                        dev.setEnergyType(regDev.getEnergyType());
                    }
                });
                subitem.setDevSubitemMapList(devSubitemMaps);
            }
        }
        return subitem;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveDevSubitemMap(DimSubitem dimSubitem) {
        if (CollectionUtils.isNotEmpty(dimSubitem.getDevSubitemMapList())) {
            //删除操作：
            List<DevSubitemMap> dbDataList = devSubitemMapService.list(Wrappers.<DevSubitemMap>lambdaQuery().eq(DevSubitemMap::getSubitemId, dimSubitem.getId()));
            List<DevSubitemMap> paramList = dimSubitem.getDevSubitemMapList();
            List<DevSubitemMap> resultList = dbDataList.stream()
                    .filter(db -> paramList.stream().filter(item -> item.getId() != null).noneMatch(param -> param.getId().equals(db.getId())))
                    .collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(resultList)) {
                List<Long> ids = resultList.stream().map(DevSubitemMap::getSubitemId).collect(Collectors.toList());
                List<String> unitNos = resultList.stream().map(DevSubitemMap::getUnitNo).collect(Collectors.toList());
                //递归后存放的分项id集合
                List<Long> subitemIds = new ArrayList<>();
                subitemIds.addAll(ids);
                subitemIds = recursiveSelect(ids, subitemIds);
                devSubitemMapService.remove(Wrappers.<DevSubitemMap>lambdaQuery().in(DevSubitemMap::getSubitemId, subitemIds).in(DevSubitemMap::getUnitNo, unitNos));
            }
            paramList.forEach(item -> {
                item.setSubitemId(dimSubitem.getId());
                List<RegDev> regDevs = regDevMapper.selectList(Wrappers.<RegDev>lambdaQuery().eq(RegDev::getUnitNo, item.getUnitNo()));
                if (CollectionUtils.isNotEmpty(regDevs)) {
                    RegDev regDev = regDevs.get(0);
                    item.setRegDevId(regDev.getId());
                    item.setEnergyType(regDev.getEnergyType());
                    List<DevSubitemMap> list = devSubitemMapService.list(Wrappers.<DevSubitemMap>lambdaQuery().eq(DevSubitemMap::getSubitemId, dimSubitem.getId()).eq(DevSubitemMap::getUnitNo, item.getUnitNo()));
                    if (list.size() > 0) {
                        devSubitemMapService.updateById(item);
                    } else {
                        item.setId(null);
                        devSubitemMapService.save(item);
                    }
                }
            });
            return true;
        } else {
            List<Long> ids = new ArrayList<>();
            List<Long> subitemIds = new ArrayList<>();
            ids.add(dimSubitem.getId());
            subitemIds.add(dimSubitem.getId());
            subitemIds = recursiveSelect(ids, subitemIds);
            return devSubitemMapService.remove(Wrappers.<DevSubitemMap>lambdaQuery().in(DevSubitemMap::getSubitemId, subitemIds));
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeSubitemBatchByIds(List<Long> ids) {
        recursiveDelete(ids);
        return true;
    }

    @Override
    public List<DevSubitemMap> getMetersById(DimSubitem dimSubitem) {
        if (dimSubitem.getParentId() != 0) {
            DimSubitem Subitem = this.getOne(Wrappers.<DimSubitem>lambdaQuery().eq(DimSubitem::getId, dimSubitem.getParentId()));
            if (ObjectUtils.isNotEmpty(Subitem)) {
                List<DevSubitemMap> list = devSubitemMapService.list(Wrappers.<DevSubitemMap>lambdaQuery().eq(DevSubitemMap::getSubitemId, Subitem.getId()));
                if (CollectionUtils.isNotEmpty(list)) {
                    list.forEach(item -> {
                        RegDev regDev = regDevMapper.selectOne(Wrappers.<RegDev>lambdaQuery().eq(RegDev::getUnitNo, item.getUnitNo()));
                        if (ObjectUtils.isNotEmpty(regDev)) {
                            item.setUnitName(regDev.getUnitName());
                        }
                    });
                    return list;
                }
            }
        }
        List<RegDev> regDevs = regDevMapper.selectList(Wrappers.<RegDev>lambdaQuery().eq(RegDev::getEnergyType, "1"));
        List<DevSubitemMap> result = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(regDevs)) {
            regDevs.forEach(item -> {
                DevSubitemMap dev = new DevSubitemMap();
                dev.setUnitNo(item.getUnitNo());
                dev.setUnitName(item.getUnitName());
                result.add(dev);
            });
        }
        return result;
    }


    @NotNull
    private Function<DimSubitem, TreeNode<Long>> getNodeFunction() {
        return cloumn -> {
            TreeNode<Long> node = new TreeNode<>();
            node.setId(cloumn.getId());
            node.setName(cloumn.getSubitemName());
            node.setParentId(cloumn.getParentId());
            // 扩展属性
            Map<String, Object> extra = new HashMap<>();
            extra.put("subitemName", cloumn.getSubitemName());
            extra.put("devSubitemMapList", cloumn.getDevSubitemMapList());
            extra.put("devSubitemNameStr", cloumn.getDevSubitemNameStr());
            node.setExtra(extra);
            return node;
        };
    }

    /**
     * 递归查询,返回分项id集合
     */
    private List<Long> recursiveSelect(List<Long> ids, List<Long> subitemIds) {
        List<DimSubitem> dimSubitems = this.listByIds(ids);
        if (CollectionUtils.isNotEmpty(dimSubitems)) {
            List<DimSubitem> list = this.list(Wrappers.<DimSubitem>lambdaQuery().in(DimSubitem::getParentId, ids));
            List<Long> chlidIds = list.stream().map(DimSubitem::getId).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(chlidIds)) {
                subitemIds.addAll(chlidIds);
                recursiveSelect(chlidIds, subitemIds);
            }
        }
        return subitemIds;
    }

    /**
     * 递归删除
     */
    private void recursiveDelete(List<Long> ids) {
        List<DimSubitem> dimSubitem = this.listByIds(ids);
        if (CollectionUtils.isNotEmpty(dimSubitem)) {
            devSubitemMapService.remove(Wrappers.<DevSubitemMap>lambdaQuery().in(DevSubitemMap::getSubitemId, ids));
            this.removeBatchByIds(ids);
            List<DimSubitem> list = this.list(Wrappers.<DimSubitem>lambdaQuery().in(DimSubitem::getParentId, ids));
            List<Long> chlidIds = list.stream().map(DimSubitem::getId).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(chlidIds)) {
                recursiveDelete(chlidIds);
            }
        }
    }

    /**
     * 桑基图
     */
    @Override
    public JSONObject powerSubitemSanchitou(String id, String startDate, String endDate) {
        JSONObject jsonPower = new JSONObject();
        List<String> idsList = new ArrayList();//递归后存放的分项id集合
        List<Map<String, Object>> listData = new ArrayList();//递归后存放的分项名称集合
        List<Map<String, Object>> tableData = new ArrayList();//递归后存放的分项名称与分项id 表格
        DimSubitem subitemOne = this.getOne(Wrappers.<DimSubitem>lambdaQuery().eq(DimSubitem::getId, id));//分项id
        Map<String, Object> map = new HashMap<>();//分项名称
        List<DimSubitem> subitemList = new ArrayList();//用来接收所有的分项信息
        if (subitemOne != null) {
            map.put("name", subitemOne.getSubitemName());//分项名称
            idsList.add(subitemOne.getId().toString());//递归后存放的分项id集合
            listData.add(map);//递归后存放的分项名称集合
            map = new HashMap<>();//分项名称
            map.put("subitemName", subitemOne.getSubitemName());
            map.put("subitemId", subitemOne.getId().toString());
            map.put("parentId", subitemOne.getParentId());
            tableData.add(map);
            subitemList = this.getBaseMapper().selectList(Wrappers.<DimSubitem>lambdaQuery());
        }
        recursionSanchitou(tableData, subitemList, idsList, listData, subitemOne);//递归查询
        // 分项桑基图 - 使用LinkedHashSet去除重复 name 不然会报错
        List<Map<String, Object>> uniqueData = listData.stream()
                .distinct() // 这不会工作，因为默认的distinct是基于整个对象的引用
                .collect(Collectors.toCollection(LinkedHashSet::new))
                .stream() // 转换回Stream以便可以进一步处理
                .collect(Collectors.toList()); // 收集回List
        jsonPower.put("data", uniqueData);//分项桑基图

        List<Map<String, Object>> listLinks = new ArrayList();//分项桑基图
        //天,月,年 分项桑基图 时间数据的拼装
        List<Map<String, Object>> resultData = sankeyTimeData(idsList, startDate, endDate);
        recursionData(listLinks, tableData, resultData, subitemList);
        jsonPower.put("links", listLinks);
        /*表格*/
        List<Map<String, Object>> table = new ArrayList();//递归后存放的分项名称与分项id
        tableData.forEach(model -> {
            Map<String, Object> mapdata = new HashMap<>();
            mapdata.put("subitemName", model.get("subitemName"));
            // 查找对应的dayData
            Optional<Map<String, Object>> dayDataOpt = resultData.stream()
                    .filter(i -> i.get("subitemId").toString().equals(model.get("subitemId").toString())) // 假设DimSubitem有getId()方法
                    .findFirst();
            // 根据dayData设置value
            mapdata.put("value", dayDataOpt.map(d -> d.get("incrValue").toString()).orElse("0")); // 使用orElse提供一个默认值
            table.add(mapdata);
        });
        jsonPower.put("tableData", table);//表格
        return jsonPower;
    }

    @Override
    public JSONObject powerSubitemBingtu(String startDate, String endDate) {
        JSONObject result = new JSONObject();
        //日期时间字符串转换
        DateTimeFormatter isoFormatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
        DateTimeFormatter customFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        //获取数据库最新的时间格式 开始时间 与 结束时间
        Map newestTime = getNewestTime(startDate, endDate);
        //当日时间与当月时间
        String startTime = null;//起始时间
        String endTime = null;//结束时间
        LocalDateTime startDateTime = null;
        LocalDateTime endDateTime = null;
        if (!newestTime.isEmpty()) {
            startDateTime = LocalDateTime.parse(newestTime.get("startTime").toString(), isoFormatter);
            startTime = startDateTime.format(customFormatter);
            endDateTime = LocalDateTime.parse(newestTime.get("endTime").toString(), isoFormatter);
            endTime = endDateTime.format(customFormatter);
        }
        //环比时间
        String YoYStartTime = null;
        String YoYendTime = null;
        //日
        if (startDate.matches("\\d{4}-\\d{2}-\\d{2}") && endDate.matches("\\d{4}-\\d{2}-\\d{2}")) {
            //获取左天的时间用来做判断用
            LocalDate today = LocalDate.now();
            // 判断开始时间和结束时间是否都在今天
            if (!startDate.equals(today.toString()) && !endDate.equals(today.toString())) {
                if (startDate.equals(endDate)) {
                    LocalDate days = LocalDate.parse(startDate, DateTimeFormatter.ofPattern("yyyy-MM-dd")).plusDays(1);
                    //获取开始时间与结束时间 用来做判断用 明天有没有数据, 没有数据则不进入
                    Map newest = getNewestTime(days.toString(), days.toString());
                    if (!newest.isEmpty()) {
                        LocalDateTime nextDayDateTime = startDateTime.plusDays(1);
                        // 格式化并打印明天的日期时间
                        LocalDateTime dateTime1 = LocalDateTime.parse(nextDayDateTime.toString(), isoFormatter);
                        endTime = dateTime1.format(customFormatter);
                    }
                } else {
                    //区间查询，根据结束时间，获取明天的00:00:00点
                    endTime = LocalDateTime.parse(endTime, customFormatter).toLocalDate().plusDays(1).atStartOfDay().format(customFormatter);
                }
            } else {
            }
        }
        //月
        if (startDate.matches("^\\d{4}-(0[1-9]|1[0-2])$") && endDate.matches("^\\d{4}-(0[1-9]|1[0-2])$")) {
            //1.获取当前月
            YearMonth currentMonth = YearMonth.from(LocalDate.now());
            if (!startDate.equals(currentMonth.toString()) && !endDate.equals(currentMonth.toString())) {
                if (startDate.equals(endDate)) {
                    YearMonth month = YearMonth.parse(startDate, DateTimeFormatter.ofPattern("yyyy-MM")).plusMonths(1);
                    //获取开始时间与结束时间 用来做判断用 明天有没有数据, 没有数据则不进入
                    Map newest = getNewestTime(month.toString(), month.toString());
                    if (!newest.isEmpty()) {
                        // 格式化并打印明天的日期时间
                        endTime = LocalDateTime.parse(newest.get("startTime").toString(), isoFormatter).format(customFormatter);
                    }
                } else {
                    //区间查询，根据结束时间，获取明天的00:00:00点
                    YearMonth month = YearMonth.parse(endDate, DateTimeFormatter.ofPattern("yyyy-MM")).plusMonths(1);
                    //获取开始时间与结束时间 用来做判断用 明天有没有数据, 没有数据则不进入
                    Map newest = getNewestTime(month.toString(), month.toString());
                    if (!newest.isEmpty()) {
                        // 格式化并打印明天的日期时间
                        endTime = LocalDateTime.parse(newest.get("startTime").toString(), isoFormatter).format(customFormatter);
                    }
                }
            } else {
            }
        }
        //年
        if (startDate.matches("^\\d{4}$") && endDate.matches("^\\d{4}$")) {
            //1.获取当前年
            Year month = Year.from(LocalDate.now());
            if (!startDate.equals(month.toString()) && !endDate.equals(month.toString())) {
                if (startDate.equals(endDate)) {
                    Year year = Year.parse(startDate, DateTimeFormatter.ofPattern("yyyy")).plusYears(1);
                    //获取开始时间与结束时间 用来做判断用 明天有没有数据, 没有数据则不进入
                    Map newest = getNewestTime(year.toString(), year.toString());
                    if (!newest.isEmpty()) {
                        // 格式化并打印明天的日期时间
                        endTime = LocalDateTime.parse(newest.get("startTime").toString(), isoFormatter).format(customFormatter);
                    }
                } else {
                    //区间查询，根据结束时间，获取明年的00:00:00点
                    Year year = Year.parse(endDate, DateTimeFormatter.ofPattern("yyyy")).plusYears(1);
                    //获取开始时间与结束时间 用来做判断用 明天有没有数据, 没有数据则不进入
                    Map newest = getNewestTime(year.toString(), year.toString());
                    if (!newest.isEmpty()) {
                        // 格式化并打印明天的日期时间
                        endTime = LocalDateTime.parse(newest.get("startTime").toString(), isoFormatter).format(customFormatter);
                    }
                }
            } else {
            }
        }
        AtomicReference<List<DimSubitem>> subitemList = new AtomicReference<>(new ArrayList<>());
        List<String> idsList = new ArrayList<>();//递归后存放的分项id集合
        List<DimSubitem> DimSubitems = this.getBaseMapper().selectList(Wrappers.<DimSubitem>lambdaQuery().eq(DimSubitem::getParentId, 0));
        if (!DimSubitems.isEmpty()) {
            DimSubitems.forEach(item -> {
                List<DimSubitem> dimList = this.getBaseMapper().selectList(Wrappers.<DimSubitem>lambdaQuery().eq(DimSubitem::getParentId, item.getId()));
                dimList.forEach(item1 -> {
                    subitemList.get().add(item1);
                    idsList.add(String.valueOf(item1.getId()));
                });
            });
        }
        //查出来的数据
        List<Map<String, Object>> subitemLinks = devSubitemMapService.powerSubitemLinks(startTime, endTime, idsList);
        // 取前五个元素
        List<Map<String, Object>> subitemLinksFive = subitemLinks.subList(0, Math.min(subitemLinks.size(), 5));
        List<Map<String, Object>> resultData = new ArrayList();
        subitemLinksFive.forEach(item -> {
            Map map = new HashMap<>();
            map.put("value", new BigDecimal(String.valueOf(item.get("incrValue"))).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
            Optional<DimSubitem> optionalsubitem = subitemList.get().stream()
                    .filter(f -> f.getId().equals(item.get("subitemId")))
                    .findFirst(); // 使用 findFirst 获取第一个匹配的元素
            DimSubitem subitem = optionalsubitem.orElse(null); // 如果找不到，则返回 null
            if (subitem != null) {
                map.put("name", subitem.getSubitemName());
            }
            resultData.add(map);
        });
        Map map = new HashMap<>();
        // 剩下的元素集合在一起  
        List<Map<String, Object>> remaining = subitemLinks.subList(5, subitemLinks.size());
        map.put("name", "其他");
        Double totalCount = remaining.stream()
                .mapToDouble(m -> {
                    if (m.containsKey("incrValue")) {
                        return (Double) m.get("incrValue");
                    } else {
                        return 0;
                    }
                }).sum();
        map.put("value", totalCount);
        resultData.add(map);
        result.put("data", resultData);
        return result;
    }

    /*
     * 分项桑基图-递归查询
     * */
    private List<Map<String, Object>> recursionSanchitou(List<Map<String, Object>> tableData, List<DimSubitem> subitemList, List idsList, List<Map<String, Object>> listData, DimSubitem subitemOne) {
        if (ObjectUtils.isNotEmpty(subitemOne)) {
            subitemList.stream().forEach(DimSubitem -> {
                // 在这里处理每一个DimSubitem对象
                if (subitemOne.getId().equals(DimSubitem.getParentId())) {
                    Map<String, Object> map = new HashMap<>();
                    map.put("name", DimSubitem.getSubitemName());
                    idsList.add(DimSubitem.getId().toString());
                    listData.add(map);
                    Map<String, Object> maptable = new HashMap<>();
                    maptable.put("subitemName", DimSubitem.getSubitemName());
                    maptable.put("subitemId", DimSubitem.getId().toString());
                    maptable.put("parentId", DimSubitem.getParentId());
                    tableData.add(maptable);
                    recursionSanchitou(tableData, subitemList, idsList, listData, DimSubitem);
                }
            });
        }
        return listData;
    }

    //天,月,年 分项桑基图 时间数据的拼装
    private List<Map<String, Object>> sankeyTimeData(List<String> idsList, String startDate, String endDate) {
        List<Map<String, Object>> resultData = new ArrayList();
        //日期时间字符串转换
        DateTimeFormatter isoFormatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
        DateTimeFormatter customFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        //获取数据库最新的时间格式 开始时间 与 结束时间
        Map newestTime = getNewestTime(startDate, endDate);
        //当日时间与当月时间
        String startTime = null;//起始时间
        String endTime = null;//结束时间
        LocalDateTime startDateTime = null;
        LocalDateTime endDateTime = null;
        if (!newestTime.isEmpty()) {
            startDateTime = LocalDateTime.parse(newestTime.get("startTime").toString(), isoFormatter);
            startTime = startDateTime.format(customFormatter);
            endDateTime = LocalDateTime.parse(newestTime.get("endTime").toString(), isoFormatter);
            endTime = endDateTime.format(customFormatter);
        }
        //日
        if (startDate.matches("\\d{4}-\\d{2}-\\d{2}") && endDate.matches("\\d{4}-\\d{2}-\\d{2}")) {
            //获取左天的时间用来做判断用
            LocalDate today = LocalDate.now();
            // 判断开始时间和结束时间是否都在今天
            if (!startDate.equals(today.toString()) && !endDate.equals(today.toString())) {
                if (startDate.equals(endDate)) {
                    LocalDate days = LocalDate.parse(startDate, DateTimeFormatter.ofPattern("yyyy-MM-dd")).plusDays(1);
                    //获取开始时间与结束时间 用来做判断用 明天有没有数据, 没有数据则不进入
                    Map newest = getNewestTime(days.toString(), days.toString());
                    if (!newest.isEmpty()) {
                        LocalDateTime nextDayDateTime = startDateTime.plusDays(1);
                        // 格式化并打印明天的日期时间
                        LocalDateTime dateTime1 = LocalDateTime.parse(nextDayDateTime.toString(), isoFormatter);
                        endTime = dateTime1.format(customFormatter);
                    }
                } else {
                    //区间查询，根据结束时间，获取明天的00:00:00点
                    endTime = LocalDateTime.parse(endTime, customFormatter).toLocalDate().plusDays(1).atStartOfDay().format(customFormatter);
                }
            }
        }
        //月
        if (startDate.matches("^\\d{4}-(0[1-9]|1[0-2])$") && endDate.matches("^\\d{4}-(0[1-9]|1[0-2])$")) {
            //1.获取当前月
            YearMonth currentMonth = YearMonth.from(LocalDate.now());
            if (!startDate.equals(currentMonth.toString()) && !endDate.equals(currentMonth.toString())) {
                if (startDate.equals(endDate)) {
                    YearMonth month = YearMonth.parse(startDate, DateTimeFormatter.ofPattern("yyyy-MM")).plusMonths(1);
                    //获取开始时间与结束时间 用来做判断用 明天有没有数据, 没有数据则不进入
                    Map newest = getNewestTime(month.toString(), month.toString());
                    if (!newest.isEmpty()) {
                        // 格式化并打印明天的日期时间
                        endTime = LocalDateTime.parse(newest.get("startTime").toString(), isoFormatter).format(customFormatter);
                    }
                } else {
                    //区间查询，根据结束时间，获取明天的00:00:00点
                    YearMonth month = YearMonth.parse(endDate, DateTimeFormatter.ofPattern("yyyy-MM")).plusMonths(1);
                    //获取开始时间与结束时间 用来做判断用 明天有没有数据, 没有数据则不进入
                    Map newest = getNewestTime(month.toString(), month.toString());
                    if (!newest.isEmpty()) {
                        // 格式化并打印明天的日期时间
                        endTime = LocalDateTime.parse(newest.get("startTime").toString(), isoFormatter).format(customFormatter);
                    }
                }
            }
        }
        //年
        if (startDate.matches("^\\d{4}$") && endDate.matches("^\\d{4}$")) {
            //1.获取当前年
            Year month = Year.from(LocalDate.now());
            if (!startDate.equals(month.toString()) && !endDate.equals(month.toString())) {
                if (startDate.equals(endDate)) {
                    Year year = Year.parse(startDate, DateTimeFormatter.ofPattern("yyyy")).plusYears(1);
                    //获取开始时间与结束时间 用来做判断用 明天有没有数据, 没有数据则不进入
                    Map newest = getNewestTime(year.toString(), year.toString());
                    if (!newest.isEmpty()) {
                        // 格式化并打印明天的日期时间
                        endTime = LocalDateTime.parse(newest.get("startTime").toString(), isoFormatter).format(customFormatter);
                    }
                } else {
                    //区间查询，根据结束时间，获取明年的00:00:00点
                    Year year = Year.parse(endDate, DateTimeFormatter.ofPattern("yyyy")).plusYears(1);
                    //获取开始时间与结束时间 用来做判断用 明天有没有数据, 没有数据则不进入
                    Map newest = getNewestTime(year.toString(), year.toString());
                    if (!newest.isEmpty()) {
                        // 格式化并打印明天的日期时间
                        endTime = LocalDateTime.parse(newest.get("startTime").toString(), isoFormatter).format(customFormatter);
                    }
                }
            }
        }
        //分项能耗统计
        return devSubitemMapService.powerSubitemLinks(startTime, endTime, idsList);
    }

    /*
     * listLinks 用来接收数据用的
     * tableData 分项数据接受名称
     * resultData 分项能耗统计数据
     * subitemList 全部数据
     * */
    private List<Map<String, Object>> recursionData(List<Map<String, Object>> listLinks, List<Map<String, Object>> tableData,
                                                    List<Map<String, Object>> resultData, List<DimSubitem> subitemList) {
        List<Map<String, Object>> result = tableData.stream()
                .map(tableRow -> {
                    // 根据tableRow的subitemId去subitemList中查找父id为tableRow的parentId的数据
                    List<DimSubitem> parentsubitem = subitemList.stream()
                            .filter(DimSubitem -> {
                                String subitemId = tableRow.get("subitemId").toString(); // 确保这里能安全转换为String
                                String parentId = DimSubitem.getParentId().toString(); // 确保这里能安全转换为String
                                return subitemId.equals(parentId);
                            })
                            .collect(Collectors.toList());
                    // 如果找到了父分项数据，将其添加到tableRow中或进行其他处理
                    if (!parentsubitem.isEmpty()) {
                        parentsubitem.forEach(item -> {
                            Map<String, Object> map = new HashMap<>();
                            map.put("source", tableRow.get("subitemName").toString()); // 确保这里能安全转换为String
                            map.put("target", item.getSubitemName()); // 假设DimSubitem有getSubitemName()方法
                            // 查找对应的dayData
                            Optional<Map<String, Object>> dayDataOpt = resultData.stream()
                                    .filter(i -> i.get("subitemId").equals(item.getId())) // 假设DimSubitem有getId()方法
                                    .findFirst();
                            // 根据dayData设置value
                            map.put("value", dayDataOpt.map(d -> d.get("incrValue").toString()).orElse("0")); // 使用orElse提供一个默认值
                            // 将map添加到listLinks中（确保listLinks已定义）
                            listLinks.add(map);
                        });
                    }
                    // 不需要修改tableRow，直接返回
                    return tableRow;
                })
                .collect(Collectors.toList()); // 收集流的结果到result列表中
        return listLinks;
    }

    /*
     * 能耗报表
     * */
    @Override
    public List<Map<String, Object>> getSubitemReportPage(String ids, String date) {
        JSONObject backResult = new JSONObject();
        List<DimSubitem> subitemLIst = new ArrayList<>();//分项数据
        List<String> idList = new ArrayList<>();//递归后存放的分项id集合
        //分项id 不等于空的时候
        if (StringUtils.isNotBlank(ids)) {
            String[] id = ids.split(",");
            idList = Arrays.asList(id);
            subitemLIst = this.getBaseMapper().selectList(Wrappers.<DimSubitem>lambdaQuery().in(DimSubitem::getId, idList));
        } else {
            subitemLIst = this.getBaseMapper().selectList(Wrappers.<DimSubitem>lambdaQuery());
            List<String> finalIdList = idList;
            subitemLIst.forEach(item -> {
                finalIdList.add(item.getId().toString());
            });
        }
        String layerStartTime = null;
        String layerEndTime = null;
        List<Map<String, Object>> reportlist = new ArrayList<>();//报表数据
        String type = ""; //1日 2月 3年
        //日
        if (date.matches("\\d{4}-\\d{2}-\\d{2}")) {
            // Create图层时间
            layerStartTime = date + " 01";//开始时间
            // 解析给定的日期字符串
            LocalDate givenDate = LocalDate.parse(date, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
            // 获取明天的日期
            LocalDate nextDay = givenDate.plusDays(1);
            layerEndTime = nextDay.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + " 00";
            reportlist = devSubitemMapService.dayReport(layerStartTime, layerEndTime, idList);
            type = "1";
        }
        //月
        if (date.matches("^\\d{4}-(0[1-9]|1[0-2])$")) {
            String BlurDate = date.replaceAll("-", "");
            reportlist = devSubitemMapService.monthReport(BlurDate, idList);
            type = "2";
        }
        //年
        if (date.matches("^\\d{4}$")) {
            reportlist = devSubitemMapService.yearReport(date, idList);
            type = "3";
        }
        return datReportMap(type, subitemLIst, reportlist);
    }

    //报表数据组装
    public List<Map<String, Object>> datReportMap(String type, List<DimSubitem> subitemLIst, List<Map<String, Object>> reportlist) {
        List<Map<String, Object>> reportList = new ArrayList<>();
        subitemLIst.forEach(item -> {
                    Map<String, Object> map = new HashMap<>();
                    map.put("reportName", item.getSubitemName());
                    AtomicReference<Double> totalSum = new AtomicReference<>(0.0);
                    reportlist.forEach(report -> {
                        if (report.get("subitemId").toString().equals(item.getId().toString())) {
                            if (type.equals("1")) {
                                map.put("d_" + report.get("createTime").toString(), report.get("totalValue").toString());
                            }
                            if (type.equals("2")) {
                                map.put("m_" + report.get("createTime").toString(), report.get("totalValue").toString());
                            }
                            if (type.equals("3")) {
                                map.put("y_" + report.get("createTime").toString(), report.get("totalValue").toString());
                            }
                            totalSum.updateAndGet(v -> v + Double.valueOf(report.get("totalValue").toString()));
                        }
                    });
                    map.put("totalSum", new BigDecimal(String.valueOf(totalSum)).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
                    reportList.add(map);
                }
        );
        return reportList;
    }

    /*
     * 能耗对比
     * */
    @Override
    public JSONObject powerSubitemContrast(String ids, String startDate, String endDate) {
        String[] id = ids.split(",");
        List<String> idList = Arrays.asList(id);
        List<DimSubitem> subitemList = new ArrayList<>();
        if (StringUtils.isNotBlank(ids)) {
            subitemList = this.getBaseMapper().selectList(Wrappers.<DimSubitem>lambdaQuery().in(DimSubitem::getId, idList));
        }
        String layerStartTime = null;
        String layerEndTime = null;
        List<Map<String, Object>> reportlist = new ArrayList<>();//报表数据
        String type = ""; //1日 2月 3年
        //时
        if (startDate.matches("^\\d{4}-\\d{2}-\\d{2}\\s\\d{2}$") && endDate.matches("^\\d{4}-\\d{2}-\\d{2}\\s\\d{2}$")) {
            reportlist = devSubitemMapService.dayReport(startDate, endDate, idList);
            List<Map<String, Object>> maplist = new ArrayList<>();//报表数据
            reportlist.forEach(r -> {
                Map<String, Object> map = new HashMap<>();
                map.put("totalValue", r.get("totalValue"));
                map.put("subitemId", r.get("subitemId"));
                LocalDateTime localDateTime = LocalDateTime.parse(r.get("timeValue").toString(), DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm"));
                map.put("createTime",localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                maplist.add(map);
            });
            reportlist = maplist;
            type = "4";
        }
        //日对比
        if (startDate.matches("\\d{4}-\\d{2}-\\d{2}") && endDate.matches("\\d{4}-\\d{2}-\\d{2}")) {
            //当天数据
            if (startDate.equals(endDate)) {
                //   Create图层时间
                layerStartTime = startDate + " 01";//开始时间
                // 解析给定的日期字符串
                LocalDate givenDate = LocalDate.parse(endDate, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                // 获取明天的日期
                LocalDate nextDay = givenDate.plusDays(1);
                layerEndTime = nextDay.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + " 00";
                reportlist = devSubitemMapService.dayReport(layerStartTime, layerEndTime, idList);
                type = "1";
            } else {
                layerStartTime = startDate.replaceAll("-", "");
                layerEndTime = endDate.replaceAll("-", "");
                reportlist = devSubitemMapService.daySectionReport(layerStartTime, layerEndTime, idList);
                type = "4";//其他
            }
        }
        //月
        if (startDate.matches("^\\d{4}-(0[1-9]|1[0-2])$") && endDate.matches("^\\d{4}-(0[1-9]|1[0-2])$")) {
            //前月数据
            if (startDate.equals(endDate)) {
                String BlurDate = startDate.replaceAll("-", "");
                reportlist = devSubitemMapService.monthReport(BlurDate, idList);
                type = "2";
            } else {
                layerStartTime = startDate.replaceAll("-", "");
                layerEndTime = endDate.replaceAll("-", "");
                reportlist = devSubitemMapService.monthSectionReport(layerStartTime, layerEndTime, idList);
                type = "4";
            }
        }
        // 年
        if (startDate.matches("^\\d{4}$") && endDate.matches("^\\d{4}$")) {
            if (startDate.equals(endDate)) {
                reportlist = devSubitemMapService.yearReport(startDate, idList);
                type = "3";
            } else {
                //年的区间 开始时间
                Calendar calendar = Calendar.getInstance();
                calendar.set(Integer.parseInt(startDate), Calendar.JANUARY, 1); // 年份、月份（从0开始，1代表1月）、日期
                layerStartTime = new SimpleDateFormat("yyyy-MM-dd 00:00:00").format(calendar.getTime());
                //年的区间 接受时间
                calendar.set(Integer.parseInt(endDate), Calendar.DECEMBER, 31); // 年份、月份（从0开始，1代表1月）、日期
                layerEndTime = new SimpleDateFormat("yyyy-MM-dd 23:00:00").format(calendar.getTime());
                reportlist = devSubitemMapService.yearSectionReport(layerStartTime, layerEndTime, idList);
                type = "4";
            }
        }
        return layerContrast(type, subitemList, reportlist);
    }

    //数据组装
    public JSONObject layerContrast(String type, List<DimSubitem> lists, List<Map<String, Object>> reportlist) {
        JSONObject result = new JSONObject();
        JSONObject resultPower = new JSONObject();
        List<Map<String, Object>> tableList = new ArrayList<>();
        List<String> legendData = new ArrayList<>();//递归后存放的名称
        List<String> xAxis = new ArrayList<>();
        //日
        if (type.equals("1")) {
            for (int h = 1; h < 25; h++) {
                String strHour = String.format("%02d", h);
                xAxis.add(strHour);
            }
        }
        //月
        if (type.equals("2")) {
            for (int day = 1; day <= 31; day++) {
                // 输出两位数的日期，如果是一位数则在前面补0
                String strDay = String.format("%02d", day);
                xAxis.add(strDay);
            }
        }
        //年
        if (type.equals("3")) {
            for (int m = 1; m < 13; m++) {
                String strMonth = String.format("%02d", m);
                xAxis.add(strMonth);
            }
        }
        //其他
        if (type.equals("4")) {
            List<String> finalXAxis = xAxis;
            reportlist.forEach(r -> {
                finalXAxis.add(r.get("createTime").toString());
            });
            xAxis = finalXAxis.stream()
                    .distinct() // 去重
                    .sorted() // 排序（自然顺序）
                    .collect(Collectors.toList());
        }
        List<Map<String, Object>> serieslist = new ArrayList<>();//图层拼装数据

        List<String> finalXAxis1 = xAxis;
        lists.forEach(item -> {
            Map<String, Object> map = new HashMap<>();
            legendData.add(item.getSubitemName()); //图例名称
            map.put("name", item.getSubitemName());//图例名称
            List<String> seriesData = new ArrayList<>();//图层数据
            Map<String, Object> tableMap = new HashMap<>();
            tableMap.put("reportName", item.getSubitemName());//表格头部名称
            List<Map<String, Object>> yearData = reportlist.stream().filter(bo -> bo.get("subitemId").equals(item.getId()))
                    .collect(Collectors.toList());
            AtomicReference<Double> sumTotal = new AtomicReference<>(0.0);
            finalXAxis1.stream().forEach(x -> {
                List<Map<String, Object>> data = yearData.stream().filter(y -> y.get("createTime").toString().equals(x.toString()))
                        .collect(Collectors.toList());
                Double powerData = null;
                if (!data.isEmpty()) {
                    if (type.equals("1")) {
                        powerData = Double.parseDouble(data.get(0).get("totalValue").toString());
                        tableMap.put("d_" + x, powerData);
                        seriesData.add(String.valueOf(powerData));//图层数据
                        Double finalPowerData = powerData;
                        sumTotal.updateAndGet(v -> v + finalPowerData);
                    }
                    if (type.equals("2")) {
                        powerData = Double.parseDouble(data.get(0).get("totalValue").toString());
                        tableMap.put("m_" + x, powerData);
                        seriesData.add(String.valueOf(powerData));//图层数据
                        Double finalPowerData = powerData;
                        sumTotal.updateAndGet(v -> v + finalPowerData);
                    }
                    if (type.equals("3")) {
                        powerData = Double.parseDouble(data.get(0).get("totalValue").toString());
                        tableMap.put("y_" + x, powerData);
                        seriesData.add(String.valueOf(powerData));//图层数据
                        Double finalPowerData = powerData;
                        sumTotal.updateAndGet(v -> v + finalPowerData);
                    }
                    if (type.equals("4")) {
                        powerData = Double.parseDouble(data.get(0).get("totalValue").toString());
                        tableMap.put("q_" + x, powerData);
                        seriesData.add(String.valueOf(powerData));//图层数据
                        Double finalPowerData = powerData;
                        sumTotal.updateAndGet(v -> v + finalPowerData);
                    }
                } else {
                    if (type.equals("1")) {
                        tableMap.put("d_" + x, "0.0");
                        seriesData.add("-");//图层数据
                    }
                    if (type.equals("2")) {
                        tableMap.put("m_" + x, "0.0");
                        seriesData.add("-");//图层数据
                    }
                    if (type.equals("3")) {
                        tableMap.put("y_" + x, "0.0");
                        seriesData.add("-");//图层数据
                    }
                    if (type.equals("4")) {
                        tableMap.put("q_" + x, "0.0");
                        seriesData.add("-");//图层数据
                    }
                }
            });
            tableMap.put("sumTotal", new BigDecimal(String.valueOf(sumTotal)).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
            map.put("data", seriesData);//图层数据
            serieslist.add(map);//图层数据组装
            tableList.add(tableMap);//表格数据组装
        });
        resultPower.put("series", serieslist);
        resultPower.put("legendData", legendData);
        resultPower.put("xAxisData", xAxis);
        result.put("resultLayer", resultPower);//图层
        result.put("tableData", tableList);//表格
        return result;
    }

    //能耗排序
    @Override
    public List<Map<String, Object>> subitemSort(String ids, String startDate, String endDate, String order) {
        //返回数据结构接收用的
        AtomicReference<List<DimSubitem>> subitemList = new AtomicReference<>(new ArrayList<>());//分项数据
        List<String> idList;//递归后存放的区域id集合
        if (!ids.isEmpty()) {
            String[] id = ids.split(",");
            idList = Arrays.asList(id);
            List<DimSubitem> dimSubitems = this.getBaseMapper().selectList(Wrappers.<DimSubitem>lambdaQuery().in(DimSubitem::getId, idList));
            subitemList.set(dimSubitems);
        } else {
            idList = new ArrayList<>();
            //获取区域信息
            List<DimSubitem> dimSubitems = this.getBaseMapper().selectList(Wrappers.<DimSubitem>lambdaQuery().eq(DimSubitem::getParentId, 0));
            if (!dimSubitems.isEmpty()) {
                dimSubitems.forEach(item -> {
                    subitemList.set(this.getBaseMapper().selectList(Wrappers.<DimSubitem>lambdaQuery().eq(DimSubitem::getParentId, item.getId())));
                    subitemList.get().forEach(item1 -> {
                        idList.add(String.valueOf(item1.getId()));
                    });
                });
            }
        }
        //日期时间字符串转换
        DateTimeFormatter isoFormatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
        DateTimeFormatter customFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        //获取数据库最新的时间格式 开始时间 与 结束时间
        Map newestTime = getNewestTime(startDate, endDate);
        //当日时间与当月时间
        String startTime = null;//起始时间
        String endTime = null;//结束时间
        //环比的时间
        LocalDateTime startDateTime = null;
        LocalDateTime endDateTime = null;
        if (!newestTime.isEmpty()) {
            startDateTime = LocalDateTime.parse(newestTime.get("startTime").toString(), isoFormatter);
            startTime = startDateTime.format(customFormatter);
            endDateTime = LocalDateTime.parse(newestTime.get("endTime").toString(), isoFormatter);
            endTime = endDateTime.format(customFormatter);
        }
        //时
        if (startDate.matches("^\\d{4}-\\d{2}-\\d{2}\\s\\d{2}$") && endDate.matches("^\\d{4}-\\d{2}-\\d{2}\\s\\d{2}$")) {
            startTime = startDate;
            endTime= endDate;
        }
        //日
        if (startDate.matches("\\d{4}-\\d{2}-\\d{2}") && endDate.matches("\\d{4}-\\d{2}-\\d{2}")) {
            //获取左天的时间用来做判断用
            LocalDate today = LocalDate.now();
            // 判断开始时间和结束时间是否都在今天
            if (!startDate.equals(today.toString()) && !endDate.equals(today.toString())) {
                if (startDate.equals(endDate)) {
                    LocalDate days = LocalDate.parse(startDate, DateTimeFormatter.ofPattern("yyyy-MM-dd")).plusDays(1);
                    //获取开始时间与结束时间 用来做判断用 明天有没有数据, 没有数据则不进入
                    Map newest = getNewestTime(days.toString(), days.toString());
                    if (!newest.isEmpty()) {
                        LocalDateTime nextDayDateTime = startDateTime.plusDays(1);
                        // 格式化并打印明天的日期时间
                        LocalDateTime dateTime1 = LocalDateTime.parse(nextDayDateTime.toString(), isoFormatter);
                        endTime = dateTime1.format(customFormatter);
                    }
                } else {
                    //区间查询，根据结束时间，获取明天的00:00:00点
                    endTime = LocalDateTime.parse(endTime, customFormatter).toLocalDate().plusDays(1).atStartOfDay().format(customFormatter);
                }
            }
        }
        //月
        if (startDate.matches("^\\d{4}-(0[1-9]|1[0-2])$") && endDate.matches("^\\d{4}-(0[1-9]|1[0-2])$")) {
            //1.获取当前月
            YearMonth currentMonth = YearMonth.from(LocalDate.now());
            if (!startDate.equals(currentMonth.toString()) && !endDate.equals(currentMonth.toString())) {
                if (startDate.equals(endDate)) {
                    YearMonth month = YearMonth.parse(startDate, DateTimeFormatter.ofPattern("yyyy-MM")).plusMonths(1);
                    //获取开始时间与结束时间 用来做判断用 明天有没有数据, 没有数据则不进入
                    Map newest = getNewestTime(month.toString(), month.toString());
                    if (!newest.isEmpty()) {
                        // 格式化并打印明天的日期时间
                        endTime = LocalDateTime.parse(newest.get("startTime").toString(), isoFormatter).format(customFormatter);
                    }
                } else {
                    //区间查询，根据结束时间，获取明天的00:00:00点
                    YearMonth month = YearMonth.parse(endDate, DateTimeFormatter.ofPattern("yyyy-MM")).plusMonths(1);
                    //获取开始时间与结束时间 用来做判断用 明天有没有数据, 没有数据则不进入
                    Map newest = getNewestTime(month.toString(), month.toString());
                    if (!newest.isEmpty()) {
                        // 格式化并打印明天的日期时间
                        endTime = LocalDateTime.parse(newest.get("startTime").toString(), isoFormatter).format(customFormatter);
                    }
                }
            }
        }
        //年
        if (startDate.matches("^\\d{4}$") && endDate.matches("^\\d{4}$")) {
            //1.获取当前年
            Year month = Year.from(LocalDate.now());
            if (!startDate.equals(month.toString()) && !endDate.equals(month.toString())) {
                if (startDate.equals(endDate)) {
                    Year year = Year.parse(startDate, DateTimeFormatter.ofPattern("yyyy")).plusYears(1);
                    //获取开始时间与结束时间 用来做判断用 明天有没有数据, 没有数据则不进入
                    Map newest = getNewestTime(year.toString(), year.toString());
                    if (!newest.isEmpty()) {
                        // 格式化并打印明天的日期时间
                        endTime = LocalDateTime.parse(newest.get("startTime").toString(), isoFormatter).format(customFormatter);
                    }
                } else {
                    //区间查询，根据结束时间，获取明年的00:00:00点
                    Year year = Year.parse(endDate, DateTimeFormatter.ofPattern("yyyy")).plusYears(1);
                    //获取开始时间与结束时间 用来做判断用 明天有没有数据, 没有数据则不进入
                    Map newest = getNewestTime(year.toString(), year.toString());
                    if (!newest.isEmpty()) {
                        // 格式化并打印明天的日期时间
                        endTime = LocalDateTime.parse(newest.get("startTime").toString(), isoFormatter).format(customFormatter);
                    }
                }
            }
        }

        //分项能耗排序
        List<Map<String, Object>> resultData = new ArrayList<>();//排序数据
        if (startTime != null && endTime != null) {
            resultData = devSubitemMapService.branchSortRank(startTime, endTime, idList);
        }
        return subitemSortData(order,subitemList, resultData);
    }


    //分项能耗排序-数据组装
    private List<Map<String, Object>> subitemSortData(String order,AtomicReference<List<DimSubitem>> subitemList, List<Map<String, Object>> resultData) {
        List<Map<String, Object>> tableData = new ArrayList<>();//表格数据>
        //分项数据累加总和 -计算百分比
        Double totalCount = resultData.stream()
                .mapToDouble(map -> {
                    if (map.containsKey("incrValue")) {
                        return (Double) map.get("incrValue");
                    } else {
                        return 0;
                    }
                }).sum();
        resultData.forEach(item -> {
            Map<String, Object> map = new HashMap<>();
            Double percent = (Double.parseDouble(item.get("incrValue").toString()) / Double.parseDouble(totalCount.toString())) * 100; // 增长率
            map.put("percent", new BigDecimal(percent).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
            map.put("incrValue", new BigDecimal(String.valueOf(item.get("incrValue"))).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
            subitemList.get().forEach(item1 -> {
                if (item1.getId().toString().equals(item.get("subitemId").toString())) {
                    map.put("sortName", item1.getSubitemName());
                    tableData.add(map);
                }
            });
        });
        return getMaps(order,tableData);
    }
    @org.jetbrains.annotations.NotNull
    private List<Map<String, Object>> getMaps(String order, List<Map<String, Object>> mapList2) {
        List<Map<String, Object>> waterData;
        if ("desc".equals(order)) {
            waterData = mapList2.stream().sorted((c1, c2) -> MapUtils.getDouble(c2, "incrValue").
                    compareTo(MapUtils.getDouble(c1, "incrValue"))).collect(Collectors.toList());
        } else {
            waterData = mapList2.stream().sorted(Comparator.comparing(mp -> (Double) mp.get("incrValue"))).
                    collect(Collectors.toList());
        }
        return waterData;
    }
    //分项能耗占比
    @Override
    public JSONObject subitemRatio(String startDate, String endDate, String compareType, String energyType) {
        //日期时间字符串转换
        DateTimeFormatter isoFormatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
        DateTimeFormatter customFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        //获取数据库最新的时间格式 开始时间 与 结束时间
        Map newestTime = getNewestTime(startDate, endDate);
        //当日时间与当月时间
        String startTime = null;//起始时间
        String endTime = null;//结束时间
        LocalDateTime startDateTime = null;
        LocalDateTime endDateTime = null;
        if (!newestTime.isEmpty()) {
            startDateTime = LocalDateTime.parse(newestTime.get("startTime").toString(), isoFormatter);
            startTime = startDateTime.format(customFormatter);
            endDateTime = LocalDateTime.parse(newestTime.get("endTime").toString(), isoFormatter);
            endTime = endDateTime.format(customFormatter);
        }
        //环比时间
        String YoYStartTime = null;
        String YoYendTime = null;
        //日
        if (startDate.matches("\\d{4}-\\d{2}-\\d{2}") && endDate.matches("\\d{4}-\\d{2}-\\d{2}")) {
            //获取左天的时间用来做判断用
            LocalDate today = LocalDate.now();
            // 判断开始时间和结束时间是否都在今天
            if (!startDate.equals(today.toString()) && !endDate.equals(today.toString())) {
                if (startDate.equals(endDate)) {
                    LocalDate days = LocalDate.parse(startDate, DateTimeFormatter.ofPattern("yyyy-MM-dd")).plusDays(1);
                    //获取开始时间与结束时间 用来做判断用 明天有没有数据, 没有数据则不进入
                    Map newest = getNewestTime(days.toString(), days.toString());
                    if (!newest.isEmpty()) {
                        LocalDateTime nextDayDateTime = startDateTime.plusDays(1);
                        // 格式化并打印明天的日期时间
                        LocalDateTime dateTime1 = LocalDateTime.parse(nextDayDateTime.toString(), isoFormatter);
                        endTime = dateTime1.format(customFormatter);
                    }
                    //2 代表 环比逻辑处理 - 上期能耗
                    if (compareType.equals("2")) {
                        YoYStartTime = LocalDateTime.parse(startDateTime.minusDays(1).toString(), isoFormatter).format(customFormatter);
                        YoYendTime = startTime;
                    }
                } else {
                    //区间查询，根据结束时间，获取明天的00:00:00点
                    endTime = LocalDateTime.parse(endTime, customFormatter).toLocalDate().plusDays(1).atStartOfDay().format(customFormatter);
                }
            } else {
                //2 代表 环比逻辑处理 - 上期能耗
                if (compareType.equals("2")) {
                    YoYStartTime = LocalDateTime.parse(startDateTime.minusDays(1).toString(), isoFormatter).format(customFormatter);
                    YoYendTime = LocalDateTime.parse(endDateTime.minusDays(1).toString(), isoFormatter).format(customFormatter);
                }
            }
        }
        //月
        if (startDate.matches("^\\d{4}-(0[1-9]|1[0-2])$") && endDate.matches("^\\d{4}-(0[1-9]|1[0-2])$")) {
            //1.获取当前月
            YearMonth currentMonth = YearMonth.from(LocalDate.now());
            if (!startDate.equals(currentMonth.toString()) && !endDate.equals(currentMonth.toString())) {
                if (startDate.equals(endDate)) {
                    YearMonth month = YearMonth.parse(startDate, DateTimeFormatter.ofPattern("yyyy-MM")).plusMonths(1);
                    //获取开始时间与结束时间 用来做判断用 明天有没有数据, 没有数据则不进入
                    Map newest = getNewestTime(month.toString(), month.toString());
                    if (!newest.isEmpty()) {
                        // 格式化并打印明天的日期时间
                        endTime = LocalDateTime.parse(newest.get("startTime").toString(), isoFormatter).format(customFormatter);
                    }
                    //2 代表 环比逻辑处理 - 上期能耗
                    if (compareType.equals("2")) {
                        YoYStartTime = LocalDateTime.parse(startDateTime.minusMonths(1).toString(), isoFormatter).format(customFormatter);
                        YoYendTime = startTime;
                    }
                } else {
                    //区间查询，根据结束时间，获取明天的00:00:00点
                    YearMonth month = YearMonth.parse(endDate, DateTimeFormatter.ofPattern("yyyy-MM")).plusMonths(1);
                    //获取开始时间与结束时间 用来做判断用 明天有没有数据, 没有数据则不进入
                    Map newest = getNewestTime(month.toString(), month.toString());
                    if (!newest.isEmpty()) {
                        // 格式化并打印明天的日期时间
                        endTime = LocalDateTime.parse(newest.get("startTime").toString(), isoFormatter).format(customFormatter);
                    }
                }
            } else {
                //2 代表 环比逻辑处理 - 上期能耗
                if (compareType.equals("2")) {
                    YoYStartTime = LocalDateTime.parse(startDateTime.minusMonths(1).toString(), isoFormatter).format(customFormatter);
                    YoYendTime = LocalDateTime.parse(endDateTime.minusMonths(1).toString(), isoFormatter).format(customFormatter);
                }
            }
        }
        //年
        if (startDate.matches("^\\d{4}$") && endDate.matches("^\\d{4}$")) {
            //1.获取当前年
            Year month = Year.from(LocalDate.now());
            if (!startDate.equals(month.toString()) && !endDate.equals(month.toString())) {
                if (startDate.equals(endDate)) {
                    Year year = Year.parse(startDate, DateTimeFormatter.ofPattern("yyyy")).plusYears(1);
                    //获取开始时间与结束时间 用来做判断用 明天有没有数据, 没有数据则不进入
                    Map newest = getNewestTime(year.toString(), year.toString());
                    if (!newest.isEmpty()) {
                        // 格式化并打印明天的日期时间
                        endTime = LocalDateTime.parse(newest.get("startTime").toString(), isoFormatter).format(customFormatter);
                    }
                    //2 代表 环比逻辑处理 - 上期能耗
                    if (compareType.equals("1")) {
                        YoYStartTime = LocalDateTime.parse(startDateTime.minusYears(1).toString(), isoFormatter).format(customFormatter);
                        YoYendTime = startTime;
                    }
                } else {
                    //区间查询，根据结束时间，获取明年的00:00:00点
                    Year year = Year.parse(endDate, DateTimeFormatter.ofPattern("yyyy")).plusYears(1);
                    //获取开始时间与结束时间 用来做判断用 明天有没有数据, 没有数据则不进入
                    Map newest = getNewestTime(year.toString(), year.toString());
                    if (!newest.isEmpty()) {
                        // 格式化并打印明天的日期时间
                        endTime = LocalDateTime.parse(newest.get("startTime").toString(), isoFormatter).format(customFormatter);
                    }
                }
            } else {
                //2 代表 环比逻辑处理 - 上期能耗
                if (compareType.equals("1")) {
                    YoYStartTime = LocalDateTime.parse(startDateTime.minusYears(1).toString(), isoFormatter).format(customFormatter);
                    YoYendTime = LocalDateTime.parse(endDateTime.minusYears(1).toString(), isoFormatter).format(customFormatter);
                }
            }
        }
        //返回数据结构接收用的
        AtomicReference<List<DimSubitem>> subitemList = new AtomicReference<>(new ArrayList<>());//分项数据
        List<String> idList = new ArrayList<>();//递归后存放的分项id集合
        //获取分项信息
        List<DimSubitem> DimSubitems = this.getBaseMapper().selectList(Wrappers.<DimSubitem>lambdaQuery().eq(DimSubitem::getParentId, 0));
        if (!DimSubitems.isEmpty()) {
            DimSubitems.forEach(item -> {
                List<DimSubitem> dimList = this.getBaseMapper().selectList(Wrappers.<DimSubitem>lambdaQuery().eq(DimSubitem::getParentId, item.getId()));
                dimList.forEach(item1 -> {
                    subitemList.get().add(item1);
                    idList.add(String.valueOf(item1.getId()));
                });
            });
        }
        //分项数据查询技术数据
        List<Map<String, Object>> resultData = this.devSubitemMapService.subitemRatio(startTime, endTime, idList);
        List<Map<String, Object>> yoYResultData = new ArrayList<>();
        if (YoYStartTime != null && YoYendTime != null) {
            yoYResultData = this.devSubitemMapService.subitemRatio(YoYStartTime, YoYendTime, idList);
        }
        //分项数据环比与同比查询技术数据
        return subitemRatioData(resultData, yoYResultData, subitemList);
    }

    //分项能耗占比数据组装 用来计算和数据拼装的方法类
    public JSONObject subitemRatioData(List<Map<String, Object>> resultData, List<Map<String, Object>> yoYResultData, AtomicReference<List<DimSubitem>> subitemList) {
        JSONObject result = new JSONObject();//返回数据结构
        List<Map<String, Object>> pieData = new ArrayList<>();//环形图数据结构
        //subitemList 分项的数据结构用来拼装数据
        subitemList.get().forEach(item -> {
            Map<String, Object> map = new HashMap<>();
            map.put("name", item.getSubitemName());
            AtomicReference<Double> totalSum = new AtomicReference<>(0.0);//总数
            //resultData 查询出来的计算数据
            resultData.forEach(item1 -> {
                if (item.getId().equals(item1.get("subitemId"))) {
                    map.put("value", new BigDecimal(String.valueOf(item1.get("incrValue"))).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
                    map.put("subitemId", item1.get("subitemId"));
                }
                totalSum.updateAndGet(v -> v + Double.valueOf(item1.get("incrValue").toString()));
            });
            map.put("totalSum", new BigDecimal(String.valueOf(totalSum)).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
            pieData.add(map);
        });
        List<Map<String, Object>> pieCount = new ArrayList<>();//环形图数据结构
        //百分比计算
        pieData.forEach(item -> {
            System.out.println(item);
            Map<String, Object> map = new HashMap<>();
            map.put("name", item.get("name"));
            Double growthRate = (Double.parseDouble(item.get("value").toString()) / Double.parseDouble(item.get("totalSum").toString())) * 100; // 增长率
            map.put("value", new BigDecimal(String.valueOf(growthRate)).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
            pieCount.add(map);

        });
        //环形图数据Data
        result.put("pieData", pieCount);
        List<Map<String, Object>> pieTable = new ArrayList<>();//表格数据
        //环形图数据展示
        pieData.forEach(item -> {
            Map<String, Object> mapTable = new HashMap<>();
            mapTable.put("subitemName", item.get("name"));
            mapTable.put("incrValue", new BigDecimal(String.valueOf(item.get("value"))).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
            //环比与同比数据
            if (!yoYResultData.isEmpty()) {
                yoYResultData.forEach(item1 -> {
                    if (item.get("subitemId").equals(item1.get("subitemId"))) {
                        // 环比增长率
                        if (Double.parseDouble(item.get("value").toString()) > 0) {
                            Double rate = (Double.parseDouble(item.get("value").toString()) - Double.parseDouble(item1.get("incrValue").toString())) / Double.parseDouble(item1.get("incrValue").toString()) * 100; // 增长率
                            mapTable.put("growthRate", new BigDecimal(rate).setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
                        } else {
                            mapTable.put("growthRate", "-");
                        }
                    }
                });
            } else {
                mapTable.put("growthRate", "-");
            }
            pieTable.add(mapTable);
        });
        //环形图数据展示
        result.put("pieTable", pieTable);
        return result;
    }


    //获取数据库最新的时间格式 开始时间 与 结束时间
    public Map getNewestTime(String startDate, String endDate) {
        Map map = new HashMap();
        //获取当前时间
        PowerHourFlow startHourFlow = this.powerHourFlowService.getBaseMapper().selectOne(Wrappers.<PowerHourFlow>lambdaQuery()
                .like(PowerHourFlow::getTimeValue, startDate)
                .orderByAsc(PowerHourFlow::getTimeValue).last("LIMIT 1"));
        //获取上一条数据
        PowerHourFlow endHourFlow = this.powerHourFlowService.getBaseMapper().selectOne(Wrappers.<PowerHourFlow>lambdaQuery()
                .like(PowerHourFlow::getTimeValue, endDate)
                .orderByDesc(PowerHourFlow::getTimeValue).last("LIMIT 1"));
        if (ObjectUtils.isNotEmpty(startHourFlow) && ObjectUtils.isNotEmpty(endHourFlow)) {
            map.put("startTime", startHourFlow.getTimeValue().toString());
            map.put("endTime", endHourFlow.getTimeValue().toString());
        }
        return map;
    }
}